package com.young.common.client.log.core;

import com.young.common.util.CommonUtil;
import com.young.interfaces.log.model.LogDTO;
import com.young.common.util.LogUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 日志切面处理,young2使用此方式
 * Created by rookie on 2017/11/10.
 */
public class LogAspect {

    /**
     * 日志环绕处理
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable{
        //因为request在多线程环境下会出错,所以在此直接将日志中涉及request的参数进行处理
        LogDTO logDTO = new LogDTO();//日志传输对象
        //获取request参数
        Object[] args = joinPoint.getArgs();//获取方法参数
        HttpServletRequest request = null;
        ServletRequestAttributes sra = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        if (sra != null){
            request = sra.getRequest();
        }
        if (request == null){//如果sra.getRequest();的方式没有取到request(正常情况下不会发生),则通过遍历参数寻找
            for(Object obj : args){
                if (obj != null && obj instanceof HttpServletRequest){
                    request = (HttpServletRequest)obj;
                }
            }
        }
        //当参数中存在request时,生成日志所需的参数
        if (request != null){
            try {
                logDTO.setRequestParam(LogUtil.getParameterFromRequest(request));//请求参数
                logDTO.setUrl(request.getRequestURL().toString());//请求地址
                logDTO.setScheme(request.getScheme());
                logDTO.setHost(request.getServerName());
                logDTO.setPort(request.getServerPort());
                logDTO.setUri(request.getRequestURI());
                logDTO.setLoginUser(LogUtil.getLoginUser());//用户
                logDTO.setClientIp(LogUtil.getClientIpAddr(request));//ip地址
                logDTO.setBrowser(LogUtil.getClientBrowser(request));//浏览器信息
                logDTO.setOs(LogUtil.getClientOS(request));//操作系统
            }catch (Exception e){

            }
        }

        Object result = null;
        Throwable throwable = null;
        logDTO.setBeginTime(new Date());//开始时间
        logDTO.setUuid(CommonUtil.getUUID());//日志唯一编号
        try {
            //执行此方法
            result = joinPoint.proceed();
        }catch (Throwable e){
            throwable = e;
            throw e;
        }finally {
            logDTO.setResult(result);//返回结果
            logDTO.setEndTime(new Date());//结束时间
            if (throwable != null && throwable instanceof Exception){
                logDTO.setException((Exception)throwable);
            }
            LogControl.catchLog(joinPoint, logDTO);//通过日志控制器异步记录日志
        }

        return result;
    }
}
